package com.wonders.common.ws.server;

import java.io.UnsupportedEncodingException;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wonders.common.constant.CommonConstant;
import com.wonders.common.exception.XtptBusinessException;
import com.wonders.common.exception.XtptTradeException;
import com.wonders.common.parse.jaxb.JaxbService;
import com.wonders.common.parse.jaxb.config.JaxbConfig;
import com.wonders.common.parse.jaxb.entity.vo.XsdConfig;
import com.wonders.common.ws.constant.BusiCode;
import com.wonders.common.ws.constant.TradeCode;
import com.wonders.common.ws.constant.XtptConstant;
import com.wonders.common.ws.entity.vo.XtptMsg;
import com.wonders.common.ws.mapping.bean.global.Head;
import com.wonders.common.ws.mapping.bean.global.TradeMsg;
import com.wonders.common.ws.server.excutor.BaseXtptWsExcutor;
import com.wonders.common.ws.util.XtptUtil;
import com.wonders.framework.exception.FrameworkException;
import com.wonders.framework.util.web.ApplicationUtil;
import com.wonders.module.ws.excutor.XtptWsExcutorFactory;

/**
 * 协同平台1.0webservice服务
 * 
 * @author WuBin
 * 
 */
public class XtptOldWsServer {

	private Logger logger = LoggerFactory.getLogger(XtptOldWsServer.class);

	/**
	 * 接口入口
	 * 
	 * @param flag
	 *            验签标志
	 * @param xml
	 *            请求数据
	 * @param signature
	 *            数字签名
	 * @return 响应数据
	 */
	public byte[] dispatch(byte flag, String xml, byte[] signature) {
		TradeMsg reqTradeMsg = null;
		XtptMsg xtptRequest = null;
		XtptMsg xtptResponse = null;
		try {
			if (StringUtils.isEmpty(xml) || signature == null) {
				throw new XtptTradeException(TradeCode.REQUEST_PARAMS_ERROR,
						"请求参数不能为空");
			}
			xtptRequest = new XtptMsg();
			xtptRequest.setXml(xml);
			try {
				reqTradeMsg = (TradeMsg) ApplicationUtil.getBean(
						JaxbService.class).fromXML(
						XtptConstant.GLOBAL_TRADEMSG,
						CommonConstant.Interaction.REQ, xml);
			} catch (FrameworkException e) {
				throw new XtptTradeException(TradeCode.REQUEST_PARAMS_ERROR,
						"请求报文有误", e.getMessage(), e);
			}
			BaseXtptWsExcutor baseWsExcutor = ApplicationUtil.getBean(
					XtptWsExcutorFactory.class).getOldWsExcutor(
					reqTradeMsg.getHead().getBusCode());
			if (baseWsExcutor == null) {
				throw new XtptTradeException(TradeCode.INTERFACE_UNDEFINED,
						"调用接口未定义");
			}
			xtptRequest.setHead(reqTradeMsg.getHead());
			String key = StringUtils.join(reqTradeMsg.getHead().getSysCode(),
					"_", reqTradeMsg.getHead().getBusCode());
			try {
				xtptRequest.setBody(PropertyUtils.getProperty(
						ApplicationUtil.getBean(JaxbService.class).fromXML(key,
								CommonConstant.Interaction.REQ, xml), "data"));
			} catch (FrameworkException e) {
				throw new XtptTradeException(TradeCode.REQUEST_PARAMS_ERROR,
						"请求报文有误", e.getMessage(), e);
			}
			try {
				xtptResponse = baseWsExcutor.excute(xtptRequest);
			} catch (Exception e) {
				if (e instanceof XtptTradeException
						|| e instanceof XtptBusinessException) {
					throw e;
				}
				throw new XtptBusinessException(BusiCode.FAILED, "业务处理失败",
						"业务处理失败", e);
			}
			Head resHead = XtptUtil.generateResponseHead(reqTradeMsg.getHead(),
					xtptResponse);
			xtptResponse.setHead(resHead);
			byte[] response = null;
			try {
				response = packResponse(xtptResponse);
			} catch (FrameworkException e) {
				throw new XtptTradeException(TradeCode.RESPONSE_PARAMS_ERROR,
						"响应参数无法解析", e.getMessage(), e);
			}
			return response;
		} catch (Exception e) {
			if (e.getMessage() != null) {
				logger.error(e.getMessage(), e);
			} else {
				if (e instanceof XtptTradeException
						|| e instanceof XtptBusinessException) {

				} else {
					logger.error("处理接口请求失败", e);
				}
			}
			xtptResponse = new XtptMsg();
			if (e instanceof XtptTradeException) {
				xtptResponse.setTradeCode(((XtptTradeException) e)
						.getTradeCode());
				xtptResponse.setInfo(((XtptTradeException) e).getInfo());
			} else if (e instanceof XtptBusinessException) {
				xtptResponse.setTradeCode(TradeCode.SUCCESS);
				xtptResponse.setBusiCode(((XtptBusinessException) e)
						.getBusiCode());
				xtptResponse.setInfo(((XtptBusinessException) e).getInfo());
			} else {
				xtptResponse.setTradeCode(TradeCode.RESOLVE_REQUEST_ERROR);
				xtptResponse.setInfo("处理接口请求失败");
			}
			try {
				Head resHead = XtptUtil.generateResponseHead(
						reqTradeMsg.getHead(), xtptResponse);
				xtptResponse.setHead(resHead);
				return packResponse(xtptResponse);
			} catch (Exception ex) {
				logger.error("返回通用异常报文失败", ex);
				return null;
			}
		} finally {
			logger.info("请求报文:{}, 响应报文:{}",
					xtptRequest != null ? xtptRequest.getXml() : "",
					xtptResponse != null ? xtptResponse.getXml() : "");
		}
	}

	/**
	 * 组装响应数据
	 * 
	 * @param xtptRequest
	 *            响应数据
	 * @return 响应内容
	 */
	private byte[] packResponse(XtptMsg xtptResponse) {
		Object tradeMsg = null;
		String key = null;
		try {
			if (xtptResponse.getBody() != null) {
				key = StringUtils.join(xtptResponse.getHead().getSysCode(),
						"_", xtptResponse.getHead().getBusCode());
				XsdConfig xsdConfig = ApplicationUtil.getBean(JaxbConfig.class)
						.getXsdConfig(key, CommonConstant.Interaction.RES);
				tradeMsg = xsdConfig.getClazz().newInstance();
				PropertyUtils.setProperty(tradeMsg, "data",
						xtptResponse.getBody());
			} else {
				key = XtptConstant.GLOBAL_TRADEMSG;
				tradeMsg = new TradeMsg();
			}
			PropertyUtils.setProperty(tradeMsg, "head", xtptResponse.getHead());
		} catch (Exception e) {
			throw new FrameworkException("封装响应数据失败", e);
		}
		String xml = ApplicationUtil.getBean(JaxbService.class).toXml(key,
				CommonConstant.Interaction.RES, tradeMsg);
		xtptResponse.setXml(xml);
		return getResponseBytes(xml);
	}

	/**
	 * 获取字节
	 * 
	 * @param xml
	 *            报文
	 * @return 字节
	 */
	private static byte[] getResponseBytes(String xml) {
		byte[] xmlBytes = null;
		try {
			xmlBytes = xml.getBytes(XtptConstant.ENCODING);
		} catch (UnsupportedEncodingException e) {
			throw new FrameworkException("转换字符出错", e);
		}
		byte[] res = new byte[xmlBytes.length + 1];
		res[0] = 00000000;
		System.arraycopy(xmlBytes, 0, res, 1, xmlBytes.length);
		return res;
	}

}
